home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1997 January / Macworld (1997-01).dmg / Games World / Shareware Games / Arcade / Mike's Breakout / MTSound.u < prev    next >
Text File  |  1996-10-11  |  20KB  |  582 lines

  1. {send all comments/gripes/etc to ani@atlas.nmsu.edu}
  2. {feel free to use this code for whatever you'd like.  i'd be grateful i helped make someone's day just a bit brighter}
  3. {note that this is the "Sound" unit combined with my own code.  it probably should be split, the reason they are}
  4. {combined once existed, but now it probably would be better to seperate them, but i'll let you do that}
  5.  
  6. {    This file has been processed by The THINK Pascal Source Converter, v1.1.    }
  7.  
  8. {}
  9. {Created: Tuesday, March 5, 1991 at 5:12 PM}
  10. {    Sound.p}
  11. {    Pascal Interface to the Macintosh Libraries}
  12. {}
  13. {        Copyright Apple Computer, Inc.    1986-1991}
  14. {        All rights reserved}
  15. {}
  16.  
  17. unit MTSound;
  18. interface
  19.     uses
  20.         TypeConst;
  21.     const
  22.         swMode = -1;                                    { Sound Driver modes }
  23.         ftMode = 1;
  24.         ffMode = 0;
  25.  
  26.         synthCodeRsrc = 'snth';                         { Resource types used by Sound Manager }
  27.         soundListRsrc = 'snd ';
  28.  
  29.         twelfthRootTwo = 1.05946309434;
  30.         rate22khz = $56EE8BA3;                          { 22254.54545 in fixed-point }
  31.         rate11khz = $2B7745D1;                          { 11127.27273 in fixed-point }
  32.  
  33. { synthesizer numbers for SndNewChannel }
  34.         squareWaveSynth = 1;                            {square wave synthesizer}
  35.         waveTableSynth = 3;                             {wave table synthesizer}
  36.         sampledSynth = 5;                               {sampled sound synthesizer}
  37.  
  38. { old Sound Manager MACE synthesizer numbers }
  39.         MACE3snthID = 11;
  40.         MACE6snthID = 13;
  41.  
  42. { command numbers for SndDoCommand and SndDoImmediate }
  43.         nullCmd = 0;
  44.         initCmd = 1;
  45.         freeCmd = 2;
  46.         quietCmd = 3;
  47.         flushCmd = 4;
  48.         reInitCmd = 5;
  49.  
  50.         waitCmd = 10;
  51.         pauseCmd = 11;
  52.         resumeCmd = 12;
  53.         callBackCmd = 13;
  54.         syncCmd = 14;
  55.         emptyCmd = 15;
  56.  
  57.         tickleCmd = 20;
  58.         requestNextCmd = 21;
  59.         howOftenCmd = 22;
  60.         wakeUpCmd = 23;
  61.         availableCmd = 24;
  62.         versionCmd = 25;
  63.         totalLoadCmd = 26;
  64.         loadCmd = 27;
  65.  
  66.         scaleCmd = 30;
  67.         tempoCmd = 31;
  68.  
  69.         freqDurationCmd = 40;
  70.         restCmd = 41;
  71.         freqCmd = 42;
  72.         ampCmd = 43;
  73.         timbreCmd = 44;
  74.         getAmpCmd = 45;
  75.  
  76.         waveTableCmd = 60;
  77.         phaseCmd = 61;
  78.  
  79.         soundCmd = 80;
  80.         bufferCmd = 81;
  81.         rateCmd = 82;
  82.         continueCmd = 83;
  83.         doubleBufferCmd = 84;
  84.         getRateCmd = 85;
  85.  
  86.         sizeCmd = 90;
  87.         convertCmd = 91;
  88.  
  89.         stdQLength = 128;
  90.         dataOffsetFlag = $8000;
  91.  
  92.         waveInitChannelMask = $07;
  93.         waveInitChannel0 = $04;
  94.         waveInitChannel1 = $05;
  95.         waveInitChannel2 = $06;
  96.         waveInitChannel3 = $07;
  97.  
  98. { channel initialization parameters }
  99.         initPanMask = $0003;                            { mask for right/left pan values }
  100.         initSRateMask = $0030;                          { mask for sample rate values }
  101.         initStereoMask = $00C0;                         { mask for mono/stereo values }
  102.         initCompMask = $FF00;                           { mask for compression IDs }
  103.  
  104.         initChanLeft = $0002;                           { left stereo channel }
  105.         initChanRight = $0003;                          { right stereo channel }
  106.         initNoInterp = $0004;                           { no linear interpolation }
  107.         initNoDrop = $0008;                             { no drop-sample conversion }
  108.         initMono = $0080;                               { monophonic channel }
  109.         initStereo = $00C0;                             { stereo channel }
  110.         initMACE3 = $0300;                              { MACE 3:1 }
  111.         initMACE6 = $0400;                              { MACE 6:1 }
  112.  
  113.         initChan0 = $0004;                              { channel 0 - wave table only }
  114.         initChan1 = $0005;                              { channel 1 - wave table only }
  115.         initChan2 = $0006;                              { channel 2 - wave table only }
  116.         initChan3 = $0007;                              { channel 3 - wave table only }
  117.  
  118.         stdSH = $00;                                    { Standard sound header encode value }
  119.         extSH = $FF;                                    { Extended sound header encode value }
  120.         cmpSH = $FE;                                    { Compressed sound header encode value }
  121.  
  122.         notCompressed = 0;                              { compression ID's }
  123.         twoToOne = 1;
  124.         eightToThree = 2;
  125.         threeToOne = 3;
  126.         sixToOne = 4;
  127.  
  128.         outsideCmpSH = 0;                               { MACE constants }
  129.         insideCmpSH = 1;
  130.         aceSuccess = 0;
  131.         aceMemFull = 1;
  132.         aceNilBlock = 2;
  133.         aceBadComp = 3;
  134.         aceBadEncode = 4;
  135.         aceBadDest = 5;
  136.         aceBadCmd = 6;
  137.         sixToOnePacketSize = 8;
  138.         threeToOnePacketSize = 16;
  139.         stateBlockSize = 64;
  140.         leftOverBlockSize = 32;
  141.  
  142.         firstSoundFormat = $0001;                       { general sound format }
  143.         secondSoundFormat = $0002;                      { special sampled sound format (HyperCard) }
  144.  
  145.         dbBufferReady = $00000001;                      { double buffer is filled }
  146.         dbLastBuffer = $00000004;                       { last double buffer to play }
  147.  
  148.         sysBeepDisable = $0000;                         { SysBeep() enable flags }
  149.         sysBeepEnable = $0001;
  150.  
  151.         unitTypeNoSelection = $FFFF;                    { unitTypes for AudioSelection.unitType }
  152.         unitTypeSeconds = $0000;
  153.  
  154.     type
  155. {            Structures for Sound Driver            }
  156.  
  157.  
  158.         FreeWave = packed array[0..30000] of Byte;
  159.  
  160.         FFSynthPtr = ^FFSynthRec;
  161.         FFSynthRec = record
  162.                 mode: INTEGER;
  163.                 count: Fixed;
  164.                 waveBytes: FreeWave;
  165.             end;
  166.  
  167.         Tone = record
  168.                 count: INTEGER;
  169.                 amplitude: INTEGER;
  170.                 duration: INTEGER;
  171.             end;
  172.  
  173.  
  174.         Tones = array[0..5000] of Tone;
  175.  
  176.         SWSynthPtr = ^SWSynthRec;
  177.         SWSynthRec = record
  178.                 mode: INTEGER;
  179.                 triplets: Tones;
  180.             end;
  181.  
  182.  
  183.         Wave = packed array[0..255] of Byte;
  184.         WavePtr = ^Wave;
  185.  
  186.         FTSndRecPtr = ^FTSoundRec;
  187.         FTSoundRec = record
  188.                 duration: INTEGER;
  189.                 sound1Rate: Fixed;
  190.                 sound1Phase: LONGINT;
  191.                 sound2Rate: Fixed;
  192.                 sound2Phase: LONGINT;
  193.                 sound3Rate: Fixed;
  194.                 sound3Phase: LONGINT;
  195.                 sound4Rate: Fixed;
  196.                 sound4Phase: LONGINT;
  197.                 sound1Wave: WavePtr;
  198.                 sound2Wave: WavePtr;
  199.                 sound3Wave: WavePtr;
  200.                 sound4Wave: WavePtr;
  201.             end;
  202.  
  203.         FTSynthPtr = ^FTSynthRec;
  204.         FTSynthRec = record
  205.                 mode: INTEGER;
  206.                 sndRec: FTSndRecPtr;
  207.             end;
  208.  
  209. {            Structures for Sound Manager            }
  210.  
  211.         SndCommand = packed record
  212.                 cmd: INTEGER;
  213.                 param1: INTEGER;
  214.                 param2: LONGINT;
  215.             end;
  216.  
  217.  
  218.         Time = LONGINT;                                 { in half milliseconds }
  219.  
  220.  
  221.     const
  222.         StdQLengthMinusOne = stdQLength - 1;
  223.  
  224.     type
  225.         SndChannelPtr = ^SndChannel;
  226.         SndChannel = packed record
  227.                 nextChan: SndChannelPtr;
  228.                 firstMod: Ptr;                              { reserved for the Sound Manager }
  229.                 callBack: ProcPtr;
  230.                 userInfo: LONGINT;
  231.                 wait: Time;                                 { The following is for internal Sound Manager use only.}
  232.                 cmdInProgress: SndCommand;
  233.                 flags: INTEGER;
  234.                 qLength: INTEGER;
  235.                 qHead: INTEGER;                             { next spot to read or -1 if empty }
  236.                 qTail: INTEGER;                             { next spot to write = qHead if full }
  237.                 queue: array[0..stdQLengthMinusOne] of SndCommand;
  238.             end;
  239.  
  240.     const
  241.         stateBlockSizeMinusOne = stateBlockSize - 1;
  242.  
  243.     type
  244. { MACE structures }
  245.         StateBlockPtr = ^StateBlock;
  246.         StateBlock = record
  247.                 stateVar: array[0..stateBlockSizeMinusOne] of INTEGER;
  248.             end;
  249.  
  250.     const
  251.         leftOverBlockSizeMinusOne = leftOverBlockSize - 1;
  252.  
  253.     type
  254.         LeftOverBlockPtr = ^LeftOverBlock;
  255.         LeftOverBlock = record
  256.                 count: LONGINT;
  257.                 sampleArea: packed array[0..leftOverBlockSizeMinusOne] of Byte;
  258.             end;
  259.  
  260.         ModRef = record
  261.                 modNumber: INTEGER;
  262.                 modInit: LONGINT;
  263.             end;
  264.  
  265.         SndListPtr = ^SndListResource;
  266.         SndListResource = record
  267.                 format: INTEGER;
  268.                 numModifiers: INTEGER;
  269.                 modifierPart: array[0..0] of ModRef;       {This is a variable length array}
  270.                 numCommands: INTEGER;
  271.                 commandPart: array[0..0] of SndCommand;    {This is a variable length array}
  272.                 dataPart: packed array[0..0] of Byte;      {This is a variable length array}
  273.             end;
  274.  
  275.         SoundHeaderPtr = ^SoundHeader;
  276.         SoundHeader = packed record
  277.                 samplePtr: Ptr;                             { if NIL then samples are in sampleArea }
  278.                 length: LONGINT;                            { length of sound in bytes }
  279.                 sampleRate: Fixed;                          { sample rate for this sound }
  280.                 loopStart: LONGINT;                         { start of looping portion }
  281.                 loopEnd: LONGINT;                           { end of looping portion }
  282.                 encode: Byte;                               { header encoding }
  283.                 baseFrequency: Byte;                        { baseFrequency value }
  284.                 sampleArea: packed array[0..0] of Byte;
  285.             end;
  286.  
  287.  
  288.         CmpSoundHeaderPtr = ^CmpSoundHeader;
  289.         CmpSoundHeader = packed record
  290.                 samplePtr: Ptr;                             { if nil then samples are in sample area }
  291.                 numChannels: LONGINT;                       { number of channels i.e. mono = 1 }
  292.                 sampleRate: Fixed;                          { sample rate in Apples Fixed point representation }
  293.                 loopStart: LONGINT;                         { loopStart of sound before compression }
  294.                 loopEnd: LONGINT;                           { loopEnd of sound before compression }
  295.                 encode: Byte;                               { data structure used , stdSH, extSH, or cmpSH }
  296.                 baseFrequency: Byte;                        { same meaning as regular SoundHeader }
  297.                 numFrames: LONGINT;                         { length in frames ( packetFrames or sampleFrames ) }
  298.                 AIFFSampleRate: extended;                   { IEEE sample rate }
  299.                 markerChunk: Ptr;                           { sync track }
  300.                 futureUse1: Ptr;                            { reserved by Apple }
  301.                 futureUse2: Ptr;                            { reserved by Apple }
  302.                 stateVars: StateBlockPtr;                   { pointer to State Block }
  303.                 leftOverSamples: LeftOverBlockPtr;          { used to save truncated samples between compression calls }
  304.                 compressionID: INTEGER;                     { 0 means no compression, non zero means compressionID }
  305.                 packetSize: INTEGER;                        { number of bits in compressed sample packet }
  306.                 snthID: INTEGER;                            { resource ID of Sound Manager snth that contains NRT C/E }
  307.                 sampleSize: INTEGER;                        { number of bits in non-compressed sample }
  308.                 sampleArea: packed array[0..0] of Byte;    { space for when samples follow directly }
  309.             end;
  310.  
  311.         ExtSoundHeaderPtr = ^ExtSoundHeader;
  312.         ExtSoundHeader = packed record
  313.                 samplePtr: Ptr;                             { if nil then samples are in sample area }
  314.                 numChannels: LONGINT;                       { number of channels,  ie mono = 1 }
  315.                 sampleRate: Fixed;                          { sample rate in Apples Fixed point representation }
  316.                 loopStart: LONGINT;                         { same meaning as regular SoundHeader }
  317.                 loopEnd: LONGINT;                           { same meaning as regular SoundHeader }
  318.                 encode: Byte;                               { data structure used , stdSH, extSH, or cmpSH }
  319.                 baseFrequency: Byte;                        { same meaning as regular SoundHeader }
  320.                 numFrames: LONGINT;                         { length in total number of frames }
  321.                 AIFFSampleRate: extended;                   { IEEE sample rate }
  322.                 markerChunk: Ptr;                           { sync track }
  323.                 instrumentChunks: Ptr;                      { AIFF instrument chunks }
  324.                 AESRecording: Ptr;
  325.                 sampleSize: INTEGER;                        { number of bits in sample }
  326.                 futureUse1: INTEGER;                        { reserved by Apple }
  327.                 futureUse2: LONGINT;                        { reserved by Apple }
  328.                 futureUse3: LONGINT;                        { reserved by Apple }
  329.                 futureUse4: LONGINT;                        { reserved by Apple }
  330.                 sampleArea: packed array[0..0] of Byte;    { space for when samples follow directly }
  331.             end;
  332.  
  333.         ConversionBlockPtr = ^ConversionBlock;
  334.         ConversionBlock = record
  335.                 destination: INTEGER;
  336.                 unused: INTEGER;
  337.                 inputPtr: CmpSoundHeaderPtr;
  338.                 outputPtr: CmpSoundHeaderPtr;
  339.             end;
  340.  
  341.         SMStatusPtr = ^SMStatus;
  342.         SMStatus = packed record
  343.                 smMaxCPULoad: INTEGER;
  344.                 smNumChannels: INTEGER;
  345.                 smCurCPULoad: INTEGER;
  346.             end;
  347.  
  348.         SCStatusPtr = ^SCStatus;
  349.         SCStatus = record
  350.                 scStartTime: Fixed;
  351.                 scEndTime: Fixed;
  352.                 scCurrentTime: Fixed;
  353.                 scChannelBusy: BOOLEAN;
  354.                 scChannelDisposed: BOOLEAN;
  355.                 scChannelPaused: BOOLEAN;
  356.                 scUnused: BOOLEAN;
  357.                 scChannelAttributes: LONGINT;
  358.                 scCPULoad: LONGINT;
  359.             end;
  360.  
  361.         AudioSelectionPtr = ^AudioSelection;
  362.         AudioSelection = packed record
  363.                 unitType: LONGINT;
  364.                 selStart: Fixed;
  365.                 selEnd: Fixed;
  366.             end;
  367.  
  368.         SndDoubleBufferPtr = ^SndDoubleBuffer;
  369.         SndDoubleBuffer = packed record
  370.                 dbNumFrames: LONGINT;
  371.                 dbFlags: LONGINT;
  372.                 dbUserInfo: array[0..1] of LONGINT;
  373.                 dbSoundData: packed array[0..0] of Byte;
  374.             end;
  375.  
  376.         SndDoubleBufferHeaderPtr = ^SndDoubleBufferHeader;
  377.         SndDoubleBufferHeader = packed record
  378.                 dbhNumChannels: INTEGER;
  379.                 dbhSampleSize: INTEGER;
  380.                 dbhCompressionID: INTEGER;
  381.                 dbhPacketSize: INTEGER;
  382.                 dbhSampleRate: Fixed;
  383.                 dbhBufferPtr: array[0..1] of SndDoubleBufferPtr;
  384.                 dbhDoubleBack: ProcPtr;
  385.             end;
  386.  
  387.     var                {--------------------------NOTE I HAVE SOME VARIABLES HERE ----------------------}
  388.         CurrStatus: SCStatusPtr;
  389.         TheChan: SndChannelPtr;
  390.         CurrCmd: SndCommand;
  391.         Sounds: array[MINSND..MAXSND] of longint;
  392.         TempH: Handle;
  393.         CurrSound: integer;
  394.         Unimportant: OSErr;
  395.         Where: Ptr;
  396.         SndOffset: longint;
  397.         CoolnessCounter: integer;
  398.  
  399.     function SndDoCommand (chan: SndChannelPtr; cmd: SndCommand; noWait: BOOLEAN): OSErr;
  400.     inline
  401.         $A803;
  402.     function SndDoImmediate (chan: SndChannelPtr; cmd: SndCommand): OSErr;
  403.     inline
  404.         $A804;
  405.     function SndNewChannel (var chan: SndChannelPtr; synth: INTEGER; init: LONGINT; userRoutine: ProcPtr): OSErr;
  406.     inline
  407.         $A807;
  408.     function SndDisposeChannel (chan: SndChannelPtr; quietNow: BOOLEAN): OSErr;
  409.     inline
  410.         $A801;
  411.     function SndPlay (chan: SndChannelPtr; sndHdl: Handle; async: BOOLEAN): OSErr;
  412.     inline
  413.         $A805;
  414.     function SndAddModifier (chan: SndChannelPtr; modifier: ProcPtr; id: INTEGER; init: LONGINT): OSErr;
  415.     inline
  416.         $A802;
  417.     function SndControl (id: INTEGER; var cmd: SndCommand): OSErr;
  418.     inline
  419.         $A806;
  420.  
  421.     procedure SetSoundVol (level: INTEGER);
  422.     procedure GetSoundVol (var level: INTEGER);
  423.     procedure StartSound (synthRec: Ptr; numBytes: LONGINT; completionRtn: ProcPtr);
  424.     procedure StopSound;
  425.     function SoundDone: BOOLEAN;
  426.  
  427.     function SndSoundManagerVersion: NumVersion;
  428.     inline
  429.         $203C, $000C, $0008, $A800;
  430.     function SndStartFilePlay (chan: SndChannelPtr; fRefNum: INTEGER; resNum: INTEGER; bufferSize: LONGINT; theBuffer: Ptr; theSelection: AudioSelectionPtr; theCompletion: ProcPtr; async: BOOLEAN): OSErr;
  431.     inline
  432.         $203C, $0D00, $0008, $A800;
  433.     function SndPauseFilePlay (chan: SndChannelPtr): OSErr;
  434.     inline
  435.         $203C, $0204, $0008, $A800;
  436.     function SndStopFilePlay (chan: SndChannelPtr; async: BOOLEAN): OSErr;
  437.     inline
  438.         $203C, $0308, $0008, $A800;
  439.     function SndChannelStatus (chan: SndChannelPtr; theLength: INTEGER; theStatus: SCStatusPtr): OSErr;
  440.     inline
  441.         $203C, $0010, $0008, $A800;
  442.     function SndManagerStatus (theLength: INTEGER; theStatus: SMStatusPtr): OSErr;
  443.     inline
  444.         $203C, $0014, $0008, $A800;
  445.     procedure SndGetSysBeepState (var sysBeepState: INTEGER);
  446.     inline
  447.         $203C, $0018, $0008, $A800;
  448.     function SndSetSysBeepState (sysBeepState: INTEGER): OSErr;
  449.     inline
  450.         $203C, $001C, $0008, $A800;
  451.     function SndPlayDoubleBuffer (chan: SndChannelPtr; theParams: SndDoubleBufferHeaderPtr): OSErr;
  452.     inline
  453.         $203C, $0020, $0008, $A800;
  454.  
  455.     function MACEVersion: NumVersion;
  456.     inline
  457.         $203C, $0000, $0010, $A800;
  458.     procedure Comp3to1 (inBuffer: Ptr; outBuffer: Ptr; cnt: LONGINT; inState: Ptr; outState: Ptr; numChannels: LONGINT; whichChannel: LONGINT);
  459.     inline
  460.         $203C, $0004, $0010, $A800;
  461.     procedure Exp1to3 (inBuffer: Ptr; outBuffer: Ptr; cnt: LONGINT; inState: Ptr; outState: Ptr; numChannels: LONGINT; whichChannel: LONGINT);
  462.     inline
  463.         $203C, $0008, $0010, $A800;
  464.     procedure Comp6to1 (inBuffer: Ptr; outBuffer: Ptr; cnt: LONGINT; inState: Ptr; outState: Ptr; numChannels: LONGINT; whichChannel: LONGINT);
  465.     inline
  466.         $203C, $000C, $0010, $A800;
  467.     procedure Exp1to6 (inBuffer: Ptr; outBuffer: Ptr; cnt: LONGINT; inState: Ptr; outState: Ptr; numChannels: LONGINT; whichChannel: LONGINT);
  468.     inline
  469.         $203C, $0010, $0010, $A800;
  470.     function MTGetSoundHeaderOffset (sndHdl: Handle; var offset: longint): oserr;
  471.     procedure InitSound;
  472.     procedure KillSound;
  473.     procedure PlaySound (WhichSound: integer);
  474.  
  475.     { UsingSound }
  476.  
  477. implementation
  478.  
  479.     procedure PlaySound;
  480.     begin
  481.         if CoolnessCounter > 0 then        {we got the hiscore sound playing, just leave it}
  482.             exit(PlaySound);
  483. {    Unimportant := SndChannelStatus(TheChan, sizeof(SCStatus), CurrStatus);}
  484. {if (CurrStatus^.scChannelBusy) then}
  485. {WhichSound := 0;}
  486. {if WhichSound <> 135 then}
  487. {begin}
  488.         with CurrCmd do
  489.             begin
  490.                 cmd := bufferCmd;
  491.                 param1 := 0;
  492.                 param2 := Sounds[WhichSound];
  493.             end;
  494.         Unimportant := SndDoImmediate(TheChan, CurrCmd);    {just stick it in a command and send it to the chan, man!}
  495.         CurrSound := WhichSound;
  496. {end;}
  497.     end;
  498.     procedure KillSound;
  499.     begin
  500.         Unimportant := snddisposechannel(thechan, true);
  501.         disposeptr(ptr(thechan));
  502.     end;            {just dispose it, Unimportant probably really IS important if you're doing something serious!}
  503.  
  504.     procedure InitSound;
  505.         var
  506.             i: integer;
  507.     begin
  508.         SetSoundVol(1);        {you can make it more/less quiet}
  509.         CurrSound := 0;        {this was going to be for priority, but that didn't quite work}
  510.         Unimportant := sndnewchannel(TheChan, sampledSynth, 0, nil);
  511.         for i := MINSND to MAXSND do
  512.             begin
  513.                 TempH := GetResource('snd ', i);
  514.                 HLock(TempH);
  515.                 Unimportant := MTGetSoundHeaderOffset(TempH, SndOffset);
  516.                 Sounds[i] := longint(Ord4(TempH^) + SndOffset);
  517.             end;        {just load each into an array to be used later}
  518.         PlaySound(128);        {play intro sound}
  519.     end;
  520.  
  521.     function MTGetSoundHeaderOffset (sndHdl: Handle; var offset: longint): oserr;
  522.         type                                                    {This function... i got it from Apple's inside mac book    }
  523.             snd1header = record                    {on sound; }
  524.                     format: integer;                        {basically it just finds the right place to        }
  525.                     numsynths: integer;                {start playing a synth sound... in format 1 or format 2,}
  526.                 end;                                              {which incidentally is obsolete and was created only to }
  527.             snd1hdrptr = ^snd1header;        {work with HyperCard...                                                                    }
  528.             snd2header = record                    {This function does the same thing as the toolbox                }
  529.                     format: integer;                        {function GetSoundHeaderOffset, but only works with the    }
  530.                     refcount: integer;                    {3.0 Sound Manager, which i didn't have.                                    }
  531.                 end;
  532.             snd2hdrptr = ^snd2header;
  533.             intptr = ^integer;
  534.             sndcmdptr = ^sndcommand;
  535.         var
  536.             myptr: ptr;
  537.             myoffset: longint;
  538.             numsynths: integer;
  539.             numcmds: integer;
  540.             isdone: boolean;
  541.             myerr: oserr;
  542.     begin
  543.         myoffset := 0;
  544.         myptr := ptr(sndhdl^);
  545.         isdone := false;
  546.         myerr := noerr;
  547.         case snd1hdrptr(myptr)^.format of
  548.             firstsoundformat: 
  549.                 begin
  550.                     numsynths := snd1hdrptr(myptr)^.numsynths;
  551.                     myptr := ptr(ord4(myptr) + sizeof(snd1header));
  552.                     myptr := ptr(ord4(myptr) + numsynths * (sizeof(integer) + sizeof(longint)));
  553.                 end;
  554.             secondsoundformat: 
  555.                 begin
  556.                     myptr := ptr(ord4(myptr) + sizeof(snd2header));
  557.                 end;
  558.             otherwise
  559.                 begin
  560.                     myerr := badformat;
  561.                     isdone := true;
  562.                 end;
  563.         end;
  564.         numcmds := intptr(myptr)^;
  565.         myptr := ptr(ord4(myptr) + sizeof(integer));
  566.         while (numcmds >= 1) and (not isdone) do
  567.             begin
  568.                 if (intptr(myptr)^ = buffercmd + dataoffsetflag) or (intptr(myptr)^ = soundcmd + dataoffsetflag) then
  569.                     begin
  570.                         myoffset := sndcmdptr(myptr)^.param2;
  571.                         isdone := true;
  572.                     end
  573.                 else
  574.                     begin
  575.                         myptr := ptr(ord4(myptr) + sizeof(sndcommand));
  576.                         numcmds := numcmds - 1;
  577.                     end;
  578.             end;
  579.         offset := myoffset;
  580.         mtgetsoundheaderoffset := myerr;
  581.     end;
  582. end.